// 检查目录是否存在：使用 fs.existsSync 检查目标文件夹是否重名。

// 生成目录结构：使用 fs.mkdirSync 创建项目文件夹和子文件夹（如 /src, /dist, /examples）。

// 渲染模板文件：这是最关键的一步

const path = require('path'); //解析路径
const fs = require('fs-extra'); // 文件系统
const inquirer = require('inquirer'); // 交互式提问
const chalk = require('chalk'); //彩色输出
const ora = require('ora'); // 用于加载动画
const execa = require('execa'); // 
const { renderTemplate } = require('../utils/render.js');



async function careate(projectName, options) {
    const cwd = process.cwd(); // 获取当前目录
    console.log(cwd);
    const targetDir = path.join(cwd, `/${projectName}`);
    if (fs.existsSync(targetDir)) {
        await fs.remove(targetDir);
    }
   const spinner = ora('Generating project configuration...').start();
    spinner.stop();
   const answers = await inquirer.prompt([
    {
        name: 'projectVersion',
        type: 'input',
        message: 'Project Version',
        default: '1.0.0'
    },
    {
        name: 'projectDescription',
        type: 'input',
        message: 'project description',
        default: 'A fanstic component library'
    },
    {
        name: 'buildTool',
        type: 'list',
        message: 'Choose build tool',
        choices: ['Rollup', 'Vite']
    },
    {
      name: 'cssPreprocessor',
      type: 'list',
      message: 'Choose CSS preprocessor:',
      choices: ['None', 'Sass', 'Less', 'Stylus']
    },
    {
        name: 'autoInstall',
        type: 'confirm',
        message: 'Install dependencies automatically?'
    }
   ]);

   spinner.succeed('Configuration collected!');

   await fs.ensureDir(targetDir);

    console.log('User answers:', answers);

   const templateContext = {
        projectName: projectName,
        projectVersion: answers.projectVersion,
        projectDescription: answers.projectDescription,
        buildTool: answers.buildTool.toLowerCase(),
        cssPreprocessor: answers.cssPreprocessor.toLowerCase()
   };

    // 2.5. 定义要渲染的模板文件列表和其目标路径
    // 这是一个映射关系：['模板源路径', '生成的目标路径']
    const filesToRender = [
        ['templates/package.json.tpl', 'package.json'],
        ['templates/README.md.tpl', 'README.md'],
        ['templates/.gitignore.tpl', '.gitignore'],
        ['templates/.npmignore.tpl', '.npmignore'],
        [`templates/${templateContext.buildTool}.config.js.tpl`, `${templateContext.buildTool}.config.js`],
        ['templates/src/Button.vue.tpl', 'src/components/Button/Button.vue'],
        ['templates/src/Button.scss.tpl', `src/components/Button/Button.${templateContext.cssPreprocessor === 'none' ? 'css' : templateContext.cssPreprocessor}`],
        ['templates/src/index.js.tpl', 'src/index.js']
    ];


    const fileSpinner = ora('Creating project files......').start();
    for(const [sourceFile, targetFile] of filesToRender) {

        const templatePath = path.join(__dirname, '..', sourceFile);
        const targetPath = path.join(targetDir, targetFile);     

        await fs.ensureDir(path.dirname(targetPath));

        if (fs.existsSync(templatePath)) {
            const content = await fs.readFile(templatePath, 'utf-8');
            const renderedContent = renderTemplate(content, templateContext);
            
            if (targetFile === 'package.json') {
                let packageData = JSON.parse(renderedContent);
                  packageData.devDependencies = generateDependencies(
                    templateContext.buildTool, 
                    templateContext.cssPreprocessor
                );
                await fs.writeFile(targetPath, JSON.stringify(packageData, null, 2), 'utf-8');
            } else {
                await fs.writeFile(targetPath, renderedContent, 'utf-8');
            }           
        } else {
            fileSpinner.warn(`Template not found: ${sourceFile}`);
        }
    }
    fileSpinner.succeed('All files created');

    const gitSpinner = ora('Initializing Git repository...').start();
    try{
        await execa('git', ['init'], { cwd: targetDir });
        gitSpinner.succeed('Git initialized successfully!');
    }catch(error){
        gitSpinner.fail('Failed to initialize Git.');
    }

    if (answers.autoInstall) {
        const installSpinner = ora('Installing dependencies with npm... This might take a while.\n').start();
        try {
            await execa('npm', ['install'], { cwd: targetDir, stdio: 'inherit' });
            installSpinner.succeed('Dependencies installed successfully!');
        } catch(error) {
            installSpinner.fail('Failed to install dependencies. You can run "npm install" manually later.');
        }
    }

    console.log();
    console.log(chalk.green(`Success! Created ${chalk.bold(projectName)} at ${chalk.bold(targetDir)}`));
    console.log();
    console.log('Inside that directory, you can run several commands:');
    console.log();
    console.log(`  ${chalk.cyan('npm run dev')}`);
    console.log('    Starts the development server (if using Vite).');
    console.log();
    console.log(`  ${chalk.cyan('npm run build')}`);
    console.log('    Bundles the library for production.');
    console.log();
    console.log('We suggest that you begin by typing:');
    console.log();
    console.log(`  ${chalk.cyan('cd')} ${projectName}`);  
    
    if(!answers.autoInstall) {
        console.log(`${chalk.cyan('npm install')}`);
    }
    console.log(`${chalk.cyan('npm run dev')}`);
    console.log();
}

function generateDependencies(buildTool, cssPreprocessor) {
    const deps = {
        'Vue': '3.0.0'
    };
    if (buildTool === 'vite') {
        deps['vite'] = "^4.0.0";
        deps['vite-plugin-vue'] = '^4.0.0'
    } else {
        deps['rollup'] = "^2.0.0";
        deps['rollup-plugin-vue'] = "^6.0.0";
        deps['@rollup/plugin-node-reesolve'] = "^13.0.0";
        deps['@rollup/plugin-commonjs'] = "^21.0.0";
        deps['@rollup/plugin-babel'] = "^5.0.0";
    }

    if (cssPreprocessor === 'sass') {
        deps['sass'] = '^1.50.0';
    } else if (cssPreprocessor === 'less') {
        deps['less'] = '^4.0.0';
    } else if (cssPreprocessor === 'stylus') {
        deps['stylus'] = '^0.55.0';
    }

    return deps;
}

module.exports = careate;
